package csa

import (
	"git.sr.ht/~mil/mobroute/src/db"
	"git.sr.ht/~mil/mobroute/src/logger"
)

// ExecuteCSA runs the connection-scan-algorithm given the input
// connections, transfers, origin walkcosts, dest walkcosts, origin time,
// and transfer cost min.
//
// The concept of a 'walkcost' is a generalized way to abstract time in
// seconds it takes to get from the stop to another point (e.g. used for
// both input and output points). The purpose of this is that the CSA
// algorithm itself doesn't need to know or do any comparisons around
// lat/lon haversine dist etc. and rather it's just an abstract concept
// of given each stop how long does it take to get from that stop
// to some target point in seconds. We don't "know" the best stop-to-stop
// route to take (which CSA output return requires), but walkcosts cover
// this.
//
// The route taken / returned is the cheapest route based on the timetable
// (connections). The entrypoint itself is unknown until the main algorithm
// loop completes. Each stop is initialized based on walkcosts, e.g. as
// originTime + walkcost. See CSA paper for details on implementation, which
// this fn is an implemntation of besides entry/exit point walkcost logic.
//
// Upon completing scanning the timetable, the time reached for each
// destination is examined and added witht the destination walkcost.
// The destination stop that is the cheapest to get to is taken and
// the path is built by iterating back up from FromSSIDU's until the root
// at which point that origin stop is assumed to be the best.
//
// The resulting returned route is an array of connections (limited from
// the input conns) which can be followed sequentially as a number of
// trips and transfers.
func ExecuteCSA(
	conns *[]db.Connection,
	transfers *[]db.Transfer,
	stopWalkcostsOrigin map[string]uint,
	stopWalkcostsDest map[string]uint,
	originTimeSeconds, implicitTransferSeconds,
	maxTransferSeconds, maxWalkSeconds, maxNTransfers uint,
) ([]*db.Connection, error) {
	logger.Infof("CSA Begin: %d conns, %d transfers, %d walks origin, %d walks dest", len(*conns), len(*transfers), len(stopWalkcostsOrigin), len(stopWalkcostsDest))
	defer logger.Info("CSA Complete")

	mapStopToArrivalDetails := ExecuteCSAMainLoop(
		conns, transfers, stopWalkcostsOrigin,
		originTimeSeconds, implicitTransferSeconds, maxTransferSeconds,
		maxNTransfers,
	)
	return ExecuteCSAFinalization(
		mapStopToArrivalDetails,
		stopWalkcostsDest,
		maxWalkSeconds,
	)
}
